package nagel_schreckenberg;

import java.util.ArrayList;

import nagel_schreckenberg.CarFactory.Placement;

public class Main {

	/**
	 * speed: 27 km/h per unit, cell length: 7.5 m
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		Frame frame1 = new Frame("tr-sim", 700, 580, 300, 100);
		if(Config.GUI){
			frame1.setVisible(true);
		}
		Panel2 panel = new Panel2(700, 580);
		frame1.add(panel);

		ArrayList<Double> wC = new ArrayList<Double>();
		ArrayList<Double> tP = new ArrayList<Double>();
		ArrayList<Double> sT = new ArrayList<Double>();
		ArrayList<Double> sC = new ArrayList<Double>();
		ArrayList<Double> wT = new ArrayList<Double>();
		ArrayList<Double> tT = new ArrayList<Double>();
		double waitingCars = 0;
		double throughPut = 0;
		double systemThrough = 0;
		double spawnedCars = 0;
		double waitingTime = 0;
		double travelTime = 0;

		long start = System.currentTimeMillis();
		for (int a = 0; a < Config.NRSIMULATIONS; a++) {
			Environment e = new Environment();
			//e.createSingleIntersection();
			//e.createRoundabout();
			e.createMultiIntersection();
			for (int i = 0; i < Config.SIMITERATIONS; i++) {
				for (Intersection in : e.getIntersections()) {
					if (in.getClass() == CarFactory.class) {
						if(i < Config.SIMITERATIONS - Config.SPAWNSTOP){
							in.spawn();
						}
						if (in.hasSpawned()) {
							spawnedCars++;
						}
						
/*						//TODO change probabilities in a pattern (maybe in a separate method)
						if(i%Config.CONTEXTCHANGE == 0){
						CarFactory temp = (CarFactory)in;
						if(temp.getPlacement() == Placement.NORTH){
							temp.setSpawnProb(.1 * i/(double)Config.CONTEXTCHANGE);
							System.out.println("Spawnprob north "+.1 * i/(double)Config.CONTEXTCHANGE);
						}
						if(temp.getPlacement() == Placement.EAST){
							temp.setSpawnProb(.1);
						}
						if(temp.getPlacement() == Placement.SOUTH){
							temp.setSpawnProb(.1);
						}
						if(temp.getPlacement() == Placement.WEST){
							temp.setSpawnProb(.1);
						}
						}
*/					}
					if (in.getClass() == CarDestructor.class) {
						systemThrough += in.countSink();
						in.clearSink();
					}
					if (in.getClass() == FourIntersection.class) {
						//in.controlLights();
						//in.greedy();
						//in.gershenson();
						in.learning();
						
					}
				}
				e.accelerate();
				e.avoidCollision();
				e.randomSlowdown();
				e.move();
				for (Lane l : e.getLanes()) {
					waitingCars += (double)l.getWaitingCars();
				}
				if(Config.GUI){
					panel.updateGraphics(e);
					panel.updateInformation(spawnedCars - systemThrough);
					panel.repaint();
					Thread.sleep(Config.VIEWTIME);
				}
			}
			System.out.println("Sim "+(a+1)+"/"+Config.NRSIMULATIONS+" finished");
			int destcounter = 0;
			for(Intersection in : e.getIntersections()){
				if(in.getClass() == CarDestructor.class){
					travelTime += in.travelTime();
					destcounter++;
				}
			}
			travelTime = travelTime / destcounter;
			waitingCars = waitingCars / Config.SIMITERATIONS;
			throughPut = e.getThroughPut();
			waitingTime = e.getWaitingTime();
			wC.add(waitingCars);
			tP.add(throughPut);
			sT.add(systemThrough);
			sC.add(spawnedCars);
			wT.add(waitingTime);
			tT.add(travelTime);
			waitingCars = 0;
			throughPut = 0;
			systemThrough = 0;
			spawnedCars = 0;
			waitingTime = 0;
			travelTime = 0;
		}
		long end = System.currentTimeMillis();

		for (int s = 0; s < sC.size(); s++) {
			spawnedCars += sC.get(s);
			throughPut += tP.get(s);
			systemThrough += sT.get(s);
			waitingCars += wC.get(s);
			waitingTime += wT.get(s);
			travelTime += tT.get(s);
		}
		spawnedCars = spawnedCars / Config.NRSIMULATIONS;
		throughPut = throughPut / Config.NRSIMULATIONS;
		systemThrough = systemThrough / Config.NRSIMULATIONS;
		waitingCars = waitingCars / Config.NRSIMULATIONS;
		waitingTime = waitingTime / Config.NRSIMULATIONS;
		travelTime = travelTime / Config.NRSIMULATIONS;
		System.out.println("Simulation time: 			" + (end - start) + " millis");
		System.out.println("Spawned: 				" + Math.round(spawnedCars) + " vehicles");
		System.out.println("System throughput: 			" + Math.round(systemThrough) + " vehicles");
		System.out.println("Vehicle throughput: 			" + (int)((systemThrough/spawnedCars)*100) + " %");
		System.out.println("Intersection throughput: 		" + Math.round(throughPut) + " vehicles");
		System.out.println("Waiting per round: 			" + Math.round(waitingCars) + " vehicles");
		System.out.println("Average waiting time per vehicle: 	" + Math.round(waitingTime) + " rounds");
		System.out.println("Average travel time per vehicle:	" + Math.round(travelTime) + " rounds");
	}
}
